package cn.flightcloud.auth.config.oauth;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

//@Configuration
public class OAuth2ServerConfig {

	private static final String DEMO_RESOURCE_ID = "order";

//	@Configuration
//	@EnableResourceServer
	protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
		@Autowired
		private AuthenticationManager authenticationManager;

		@Override
		public void configure(ResourceServerSecurityConfigurer resources) {
//			resources.authenticationManager(authenticationManager);
			resources.resourceId(DEMO_RESOURCE_ID).stateless(true);
		}

		@Override
		public void configure(HttpSecurity http) throws Exception {
			// @formatter:off
			http
					// Since we want the protected resources to be accessible in
					// the UI as well we need
					// session creation to be allowed (it's disabled by default
					// in 2.0.6)
					.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and()
					// .authorizeRequests()//
					// .anyRequest().authenticated()//
					// .and()
					// .anonymous()
					// .and()
					.authorizeRequests()
					// .antMatchers("/product/**").access("#oauth2.hasScope('select')
					// and hasRole('ROLE_USER')")
					.antMatchers("/order/**").authenticated()// 配置order访问控制，必须认证过后才可以访问
					.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
			// @formatter:on
			super.configure(http);
		}
	}

//	@Configuration
//	@EnableAuthorizationServer
	protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

		@Autowired
		private AuthenticationManager authenticationManager;
		@Autowired
		private RedisConnectionFactory redisConnectionFactory;
		@Autowired
		private UserDetailsService userDetailsService;

		@Override
		public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
			// 配置两个客户端,一个用于password认证一个用于client认证
			clients.inMemory().withClient("client_1").authorities("client")
					.secret("$2a$10$jMRUAHXzEbLpNOazqHT0TeLMOUzc7xjYHNCpkh2LH/GFCLJ7ejmfC")
					.redirectUris("http://baidu.com")// code授权添加
					.authorizedGrantTypes("authorization_code", "client_credentials", "password", "refresh_token")
					.scopes("all").resourceIds("oauth2-resource", DEMO_RESOURCE_ID).accessTokenValiditySeconds(1200)
					.refreshTokenValiditySeconds(50000).and().withClient("client_2").resourceIds(DEMO_RESOURCE_ID)
					.authorizedGrantTypes("password", "refresh_token").scopes("select").authorities("client")
					.secret("$2a$10$jMRUAHXzEbLpNOazqHT0TeLMOUzc7xjYHNCpkh2LH/GFCLJ7ejmfC");
		}

		@Bean
		public TokenStore tokenStroe() {
			return new RedisTokenStore(redisConnectionFactory);
		}

		// /**
		// * 使用非对称加密算法来对Token进行签名
		// * @return
		// */
		// @Bean
		// public JwtAccessTokenConverter jwtAccessTokenConverter() {
		// final JwtAccessTokenConverter converter = new JwtAccessToken();
		// // 导入证书
		// KeyStoreKeyFactory keyStoreKeyFactory =
		// new KeyStoreKeyFactory(new ClassPathResource("keystore.jks"),
		// "mypass".toCharArray());
		// converter.setKeyPair(keyStoreKeyFactory.getKeyPair("mytest"));
		// return converter;
		// }

		@Override
		public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
			endpoints.userDetailsService(userDetailsService).tokenStore(tokenStroe())
					// .tokenStore(new RedisTokenStore(redisConnectionFactory))
					.authenticationManager(authenticationManager);
		}

		@Override
		public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
			// 允许表单认证
			oauthServer.allowFormAuthenticationForClients();
		}

	}

}
